From: kaf24@firebug.cl.cam.ac.uk Date: Sun, 11 Jun 2006 18:23:31 +0000 (+0100) Subject: [XEN] Fix SCHEDOP_poll to work even when event channels are X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15972^2~16 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=6553807e774f9cba77210c203b3393db7f61cd53;p=xen.git [XEN] Fix SCHEDOP_poll to work even when event channels are not bound to the polling VCPU. Signed-off-by: Keir Fraser --- diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index 5437496622..bad68023f6 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -498,14 +498,14 @@ void evtchn_set_pending(struct vcpu *v, int port) { evtchn_notify(v); } - else if ( unlikely(test_bit(_VCPUF_blocked, &v->vcpu_flags) && - !local_event_delivery_is_enabled()) ) + + /* Check if some VCPU might be polling for this event. */ + if ( unlikely(test_bit(_DOMF_polling, &d->domain_flags)) && + likely(test_and_clear_bit(_DOMF_polling, &d->domain_flags)) ) { - /* - * Blocked and masked will usually mean that the VCPU executed - * SCHEDOP_poll. Kick the VCPU in case this port is in its poll list. - */ - vcpu_unblock(v); + for_each_vcpu ( d, v ) + if ( test_and_clear_bit(_VCPUF_polling, &v->vcpu_flags) ) + vcpu_unblock(v); } } @@ -801,13 +801,6 @@ long do_event_channel_op(int cmd, XEN_GUEST_HANDLE(void) arg) } -void evtchn_notify_reserved_port(struct domain *d, int port) -{ - struct evtchn *chn = evtchn_from_port(d, port); - evtchn_set_pending(d->vcpu[chn->notify_vcpu_id], port); -} - - int evtchn_init(struct domain *d) { spin_lock_init(&d->evtchn_lock); diff --git a/xen/common/schedule.c b/xen/common/schedule.c index 670ebe8fa1..49384c7468 100644 --- a/xen/common/schedule.c +++ b/xen/common/schedule.c @@ -230,13 +230,12 @@ static long do_poll(struct sched_poll *sched_poll) if ( !guest_handle_okay(sched_poll->ports, sched_poll->nr_ports) ) return -EFAULT; - /* Ensure that events are disabled: tested by evtchn_set_pending(). */ - if ( local_event_delivery_is_enabled() ) - return -EINVAL; - + /* These operations must occur in order. */ set_bit(_VCPUF_blocked, &v->vcpu_flags); + set_bit(_VCPUF_polling, &v->vcpu_flags); + set_bit(_DOMF_polling, &v->domain->domain_flags); - /* Check for events /after/ blocking: avoids wakeup waiting race. */ + /* Check for events /after/ setting flags: avoids wakeup waiting race. */ for ( i = 0; i < sched_poll->nr_ports; i++ ) { rc = -EFAULT; @@ -261,6 +260,7 @@ static long do_poll(struct sched_poll *sched_poll) stop_timer(&v->poll_timer); out: + clear_bit(_VCPUF_polling, &v->vcpu_flags); clear_bit(_VCPUF_blocked, &v->vcpu_flags); return rc; } @@ -596,7 +596,8 @@ static void vcpu_timer_fn(void *data) static void poll_timer_fn(void *data) { struct vcpu *v = data; - vcpu_unblock(v); + if ( test_and_clear_bit(_VCPUF_polling, &v->vcpu_flags) ) + vcpu_unblock(v); } /* Initialise the data structures. */ diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index bde06f79e6..70869a51af 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -355,7 +355,7 @@ extern struct domain *domain_list; /* Initialization completed. */ #define _VCPUF_initialised 4 #define VCPUF_initialised (1UL<<_VCPUF_initialised) - /* VCPU is not-runnable */ + /* VCPU is offline. */ #define _VCPUF_down 5 #define VCPUF_down (1UL<<_VCPUF_down) /* NMI callback pending for this VCPU? */ @@ -364,6 +364,9 @@ extern struct domain *domain_list; /* Avoid NMI reentry by allowing NMIs to be masked for short periods. */ #define _VCPUF_nmi_masked 9 #define VCPUF_nmi_masked (1UL<<_VCPUF_nmi_masked) + /* VCPU is polling a set of event channels (SCHEDOP_poll). */ +#define _VCPUF_polling 10 +#define VCPUF_polling (1UL<<_VCPUF_polling) /* * Per-domain flags (domain_flags). @@ -383,6 +386,9 @@ extern struct domain *domain_list; /* Domain is being debugged by controller software. */ #define _DOMF_debugging 4 #define DOMF_debugging (1UL<<_DOMF_debugging) + /* Are any VCPUs polling event channels (SCHEDOP_poll)? */ +#define _DOMF_polling 5 +#define DOMF_polling (1UL<<_DOMF_polling) static inline int vcpu_runnable(struct vcpu *v) {